package ejb.cbm.seguridad.session;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import oracle.jdbc.OracleTypes;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Service;

import ejb.cbm.commons.JdbcHelper;
import ejb.cbm.seguridad.bean.OpcionBean;
import ejb.cbm.seguridad.bean.PerfilBean;
import ejb.cbm.seguridad.entity.PerfilOpcionEntity;
import ejb.cbm.seguridad.entity.PerfilOpcionEntityId;
import ejb.cbm.seguridad.local.PerfilOpcionSessionLocal;

////@Stateless
@Service("perfilOpcionSessionLocal")
public class PerfilOpcionSession extends HibernateDaoSupport implements PerfilOpcionSessionLocal {
	
	static Logger logger = Logger.getLogger(PerfilOpcionSession.class.getName());
	
	//property constants
	public static final String FLAGACTIVO = "flagactivo";
	public static final String USUARIOREGISTRO = "usuarioregistro";
	public static final String USUARIOMODIFICACION = "usuariomodificacion";


    //@PersistenceContext 
	//private EntityManager entityManager;
	
	@Autowired
	public PerfilOpcionSession(SessionFactory sessionFactory){
		super.setSessionFactory(sessionFactory);
	}
	
    public void save(PerfilOpcionEntity transientInstance) {
    	logger.log("saving PerfilOpcionEntity instance", Level.INFO, null,null);
        try {
            getSession().persist(transientInstance);
            logger.log("save successful", Level.INFO, null,null);
        } catch (RuntimeException re) {
        	logger.log("save failed", Level.FATAL,null, re);
            throw re;
        }
    }
    
    public void delete(PerfilOpcionEntity persistentInstance) {
    	logger.log("deleting PerfilOpcionEntity instance", Level.INFO, null,null);
        try {
            getSession().delete(persistentInstance);
            logger.log("delete successful", Level.INFO, null,null);
        } catch (RuntimeException re) {
        	logger.log("delete failed", Level.FATAL,null, re);
            throw re;
        }
    }
    
    public PerfilOpcionEntity update(PerfilOpcionEntity detachedInstance) {
    	logger.log("updating PerfilOpcionEntity instance", Level.INFO, null,null);
        try {
            PerfilOpcionEntity result = (PerfilOpcionEntity) getSession().merge(detachedInstance);
            logger.log("update successful", Level.INFO, null,null);
            return result;
        } catch (RuntimeException re) {
        	logger.log("update failed", Level.FATAL,null, re);
            throw re;
        }
    }
    
    public PerfilOpcionEntity findById( PerfilOpcionEntityId id) {
    	logger.log("finding PerfilOpcionEntity instance with id: " + id, Level.INFO, null,null);
        try {
            PerfilOpcionEntity instance = (PerfilOpcionEntity) getSession().get(PerfilOpcionEntity.class, id);
            return instance;
        } catch (RuntimeException re) {
        	logger.log("find failed", Level.FATAL,null, re);
            throw re;
        }
    }
    
    //@SuppressWarnings("unchecked")
    public List<PerfilOpcionEntity> findByProperty(String propertyName, Object value) {
    	logger.log("finding PerfilOpcionEntity instance with property: " + propertyName
    						+ ", value: " + value, Level.INFO, null,null);
		try {
			String queryString = "select model from PerfilOpcionEntity model where model." 
			 						+ propertyName + "= :propertyValue";
			return getSession().createQuery(queryString)
 				.setParameter("propertyValue", value).list();
		} catch (RuntimeException re) {
			logger.log("find by property name failed", Level.FATAL,null, re);
			throw re;
		}
	}
	
	public List<PerfilOpcionEntity> findByFlagactivo(Object flagactivo) {
		return findByProperty(FLAGACTIVO, flagactivo);
	}
	
	public List<PerfilOpcionEntity> findByUsuarioregistro(Object usuarioregistro) {
		return findByProperty(USUARIOREGISTRO, usuarioregistro);
	}
	
	public List<PerfilOpcionEntity> findByUsuariomodificacion(Object usuariomodificacion) {
		return findByProperty(USUARIOMODIFICACION, usuariomodificacion);
	}
	

	//@SuppressWarnings("unchecked")
	public List<PerfilOpcionEntity> findAll() {
		logger.log("finding all PerfilOpcionEntity instances", Level.INFO, null,null);
		try {
			String queryString = "select model from PerfilOpcionEntity model";
			return getSession().createQuery(queryString).list();
		} catch (RuntimeException re) {
			logger.log("find all failed", Level.FATAL,null, re);
			throw re;
		}
	}
	
	//@SuppressWarnings("unchecked")
	public List<PerfilOpcionEntity> findbyPerfil(Long codigoPerfil) {
		logger.log("finding all PerfilOpcionEntity instances", Level.INFO, null,null);
		try {
			String queryString = "select model from PerfilOpcionEntity model where codigoPerfil = :codigoPerfil";
			return getSession().createQuery(queryString)
								.setParameter("codigoPerfil", codigoPerfil)
								.list();
		} catch (RuntimeException re) {
			logger.log("findbyPerfil", Level.FATAL,null, re);
			throw re;
		}
	}


	public List<OpcionBean> menuPrincipal(Connection con,PerfilBean perfilBean)throws SQLException{
		CallableStatement cs = null;
		ResultSet rs = null;
		OpcionBean opcion = null;
		List<OpcionBean> lista = new ArrayList<OpcionBean>();
		
		try{
			cs = con.prepareCall("call CONNEG.PQ_CONTINUIDAD.sp_obtener_menu_principal(?,?)");

			cs.setLong(1, perfilBean.getCodigoperfil());
			cs.registerOutParameter(2, OracleTypes.CURSOR);
			
			cs.executeQuery();

			rs = (ResultSet)cs.getObject(2);
			
			while(rs.next()){
				opcion = new OpcionBean();
				opcion.setCodigoopcion(rs.getLong("CODIGOOPCION"));
				opcion.setTipo(rs.getLong("TIPO"));
				opcion.setOrden(rs.getLong("ORDEN"));
				opcion.setTexto(rs.getString("TEXTO"));
				opcion.setAccion(rs.getString("ACCION"));
				opcion.setDescripcionopcion(rs.getString("DESCRIPCIONOPCION"));
				opcion.setCodigopadrenivel1(rs.getLong("CODIGOPADRENIVEL1"));
				opcion.setCodigopadrenivel2(rs.getLong("CODIGOPADRENIVEL2"));
				
				lista.add(opcion);
			}
			
		}finally{
			JdbcHelper.close(null,cs,null,null,rs);
		}
		
		return lista;
	}

	public List<OpcionBean> opcionesMenu(Connection con, 
									     Long codigoPerfil, 
									     Long padreNivel1,
									     Long padreNivel2)throws SQLException{
		CallableStatement cs = null;
		ResultSet rs = null;
		OpcionBean opcion = null;
		List<OpcionBean> lista = new ArrayList<OpcionBean>();
		
		try{
			cs = con.prepareCall("call CONNEG.PQ_CONTINUIDAD.sp_obtener_opciones_menu(?,?,?,?)");
			cs.setLong(1,codigoPerfil);
			cs.setLong(2,padreNivel1);
			cs.setLong(3,padreNivel2);
			cs.registerOutParameter(4, OracleTypes.CURSOR);
			
			cs.executeQuery();

			rs = (ResultSet)cs.getObject(4);
			
			while(rs.next()){
				opcion = new OpcionBean();
				opcion.setCodigoopcion(rs.getLong("CODIGOOPCION"));
				opcion.setTipo(rs.getLong("TIPO"));
				opcion.setOrden(rs.getLong("ORDEN"));
				opcion.setTexto(rs.getString("TEXTO"));
				opcion.setAccion(rs.getString("ACCION"));
				opcion.setDescripcionopcion(rs.getString("DESCRIPCIONOPCION"));
				opcion.setCodigopadrenivel1(rs.getLong("CODIGOPADRENIVEL1"));
				opcion.setCodigopadrenivel2(rs.getLong("CODIGOPADRENIVEL2"));
				
				lista.add(opcion);
			}
			
		}finally{
			JdbcHelper.close(null,cs,null,null,rs);
		}
		
		return lista;
	}
	
	public void persistirOpciones(List<Long> opciones, Long perfilId){
		try{
			String sql1 = null;
			if(opciones.size() > 0) {
				sql1 = "delete from PerfilOpcionEntity o where o.id.codigoperfil = :perfilId  ";
	    		sql1 += " and  o.id.codigoopcion not in (:codigoId)";
	    		Query q1 = getSession().createQuery(sql1);
	    		q1.setParameter("perfilId", perfilId);
		    	if(opciones.size() > 0) {
		    		q1.setParameterList("codigoId", opciones);
		    	}
		    	q1.executeUpdate();
	    	}
	    	
	    	
		} catch (RuntimeException re) {
	    	logger.log("opciones failed", Level.FATAL,null, re);
	        throw re;
	    }
	}
}